package edu.pku.sei.transformation.editor.model.goal;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;

import edu.pku.sei.gefcommon.descriptor.annotation.ListProperty;
import edu.pku.sei.gefcommon.descriptor.annotation.MethodProperty;
import edu.pku.sei.modeler.exceptions.FactoryNotFoundException;
import edu.pku.sei.modeler.model.common.MetaTypedList;
import edu.pku.sei.modeler.model.common.ModelRegistry;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.transformation.editor.model.ModelFactory;
import edu.pku.sei.transformation.editor.model.ModelPackage;
import edu.pku.sei.transformation.editor.model.base.NamedElement;
import edu.pku.sei.transformation.editor.model.constraint.ConstraintConnection;
import edu.pku.sei.transformation.editor.model.constraint.IConstrainableElement;

public class TransformationGoal extends NamedElement implements
		IConstrainableElement {
	private boolean isOptional = false;
	private ArrayList<GoalRelationship> relationships = new ArrayList<GoalRelationship>();
	private ArrayList<ConstraintConnection> constraints = new ArrayList<ConstraintConnection>();
	// private ArrayList<DescriptionConnection> descriptions = new
	// ArrayList<DescriptionConnection>();

	private Description goalDescription;
	private MetaTypedList endDescription = new MetaTypedList(Description.class,
			this, ModelPackage.REQUIREMENT_END_DESCRIPTION);

	public TransformationGoal() {
	}

	public Description getGoalDescription() {
		if (goalDescription == null) {
			try {
				ModelFactory f = (ModelFactory) ModelRegistry.getRegistry()
						.getFactory(this.getModel());
				goalDescription = (Description) f.createElement(
						ModelPackage.__REQUIRE_DESCRIPTION__, true);
				goalDescription.setSummary("Goal Description");
				goalDescription.setContainer(this);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (FactoryNotFoundException e) {
				e.printStackTrace();
			}
		}

		return goalDescription;
	}

	public void setGoalDescription(Description goalDescription) {
		this.goalDescription = goalDescription;
	}

	@MethodProperty(id = ModelPackage.REQUIREMENT_END_DESCRIPTION, name = "description", catalog = "Goal")
	@ListProperty(allowTypes = Description.class, newInstanceMethod = "newInstance", typeString = ModelPackage.__REQUIRE_DESCRIPTION__)
	public MetaTypedList getEndDescription() {
		return endDescription;
	}

	public boolean isOptional() {
		return isOptional;
	}

	public void setOptional(boolean isOptional) {
		this.isOptional = isOptional;
	}

	public List<GoalRelationship> getRelationships() {
		return relationships;
	}

	// public List<DescriptionConnection> getDescriptions() {
	// return this.descriptions;
	// }
	@Override
	public void serialize(Element root) {
		super.serialize(root);
		XMLUtility.xmlInstance.serializeNodes(root,
				ModelPackage.REQUIREMENT_RELATIONSHIPS, relationships);
		XMLUtility.xmlInstance.serializeNodes(root,
				ModelPackage.REQUIREMENT_CONSTRAINTS, constraints);
		XMLUtility.xmlInstance
				.serializeNode(root, ModelPackage.REQUIREMENT_GOAL_DESCRIPTION,
						this.goalDescription);
		XMLUtility.xmlInstance.serializeNodes(root,
				ModelPackage.REQUIREMENT_END_DESCRIPTION, this.endDescription);
	}

	@Override
	public void deSerialize(Element root) {
		super.deSerialize(root);
		relationships.addAll(XMLUtility.xmlInstance.deSerializeNodes(root,
				ModelPackage.REQUIREMENT_RELATIONSHIPS));
		constraints.addAll(XMLUtility.xmlInstance.deSerializeNodes(root,
				ModelPackage.REQUIREMENT_CONSTRAINTS));
		this.goalDescription = (Description) XMLUtility.xmlInstance
				.deSerializeNode(root,
						ModelPackage.REQUIREMENT_GOAL_DESCRIPTION, this);
		this.endDescription.addAll(XMLUtility.xmlInstance.deSerializeNodes(
				root, ModelPackage.REQUIREMENT_END_DESCRIPTION));
	}

	@Override
	public String toString() {
		return name;
	}

	@Override
	public List<ConstraintConnection> getConstraintConnections() {
		return constraints;
	}
}
